/*
 * File     : Structure.java
 * Created  : 1 May 2011
 *
 * Copyright © 2011 Matthew Wilson (mj. {my-surname} .uk {at} gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.dni.type.structure;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import com.googlecode.dni.ByValue;
import com.googlecode.dni.FixedSize;
import com.googlecode.dni.type.FreeableNativeObject;
import com.googlecode.dni.type.NativeObject;
import com.googlecode.dni.type.Pointer;
import com.googlecode.dni.type.cenum.CEnumUnknownValue;
import com.googlecode.dni.type.cenum.CEnumValue;
import com.googlecode.dni.type.nativetype.NativeChar;
import com.googlecode.dni.type.nativetype.NativeInt;
import com.googlecode.dni.type.nativetype.NativeLong;
import com.googlecode.dni.type.nativetype.NativeShort;
import com.googlecode.dni.type.nativetype.SizeT;
import com.googlecode.dni.type.nativetype.Unsigned;
import com.googlecode.dni.type.nativetype.WCharT;


/**
 * <p>
 *  Encapsulates a structure backed by native memory.
 * </p>
 * <style>
 *  table.type, table.type th, table.type td
 *  {
 *   border: 1px solid gray;
 *   border-collapse: collapse;
 *   padding: 0.25em;
 *  }
 * </style>
 *
 * <h3>Allowable field types</h3>
 * <p>
 *  Each field in the structure must is represented by a bean-like property.
 *  The type in Java is used to infer the type of the native field.
 * </p>
 *
 * <h4>Primitive and pointer types</h4>
 * <p>
 *  For Java primitive types, the size is set by the Java type; for example,
 *  a <code>short</code> is <em>always</em> 16 bits and signed.
 * </p>
 * <p>
 *  For natively sized types, the size is set by the platform.  The Java type
 *  has to be large enough to hold the type from all supported platforms.
 *  Where the Java type is larger than the native type, the {@link Unsigned}
 *  annotation can be used to ensure that unsigned extension is used; for
 *  example, {@link NativeChar} would promote a C 8-bit value 0xff to -1 in
 *  Java, but {@link Unsigned}&nbsp;{@link NativeChar} would promote it to 0xff.
 * </p>
 * <table class="type">
 *  <tbody>
 *   <tr><th colspan="2">C</th><th>Java</th></tr>
 *   <tr>
 *    <td colspan="2"><code>uint_32t</code></td>
 *    <td><code>boolean</code> (32-bit; zero is <code>false</code>, other values are <code>true</code>)</td>
 *   </tr>
 *   <tr>
 *    <td><code>uint_8t</code></td><td><code>int8_t</code></td>
 *    <td><code>byte</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>int16_t</code></td>
 *    <td><code>short</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>uint_16t</code></td>
 *    <td><code>char</code></li>
 *   </tr>
 *   <tr>
 *    <td><code>uint_32t</code></td><td><code>int32_t</code></td>
 *    <td><code>int</code></td>
 *   </tr>
 *   <tr>
 *    <td><code>uint_64t</code></td><td><code>int64_t</code></td>
 *    <td><code>long</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>float</code> (IEEE)</td>
 *    <td><code>float</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>double</code> (IEEE)</td>
 *    <td><code>double</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>char</code></td>
 *    <td>{@link NativeChar} <code>int</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>short</code></td>
 *    <td>{@link NativeShort} <code>int</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>int</code></td>
 *    <td>{@link NativeInt} <code>int</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>long</code></td>
 *    <td>{@link NativeLong} <code>long</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>size_t</code></td>
 *    <td>{@link SizeT} <code>long</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>wchar_t</code></td>
 *    <td>{@link WCharT} <code>int</code></td>
 *   </tr>
 *   <tr>
 *    <td colspan="2"><code>void*</code></td>
 *    <td>{@link Pointer}</td>
 *   </tr>
 *  </tbody>
 * </table>
 *
 * <h4>Enums</h4>
 * <p>
 *  C enums can be mapped to either {@link NativeInt} values or Java enums.
 *  Any Java enum can be used.  As in C, the values start at zero and increment
 *  for each constant.  A specific value can be assigned by using
 *  {@link CEnumValue}; the values then continue to increment from that (just as
 *  in C).  You may annotate at most one Java enum value with
 *  {@link CEnumUnknownValue} to indicate that that value will be returned if
 *  the C enum value is not recognised; if you do not, an unrecognised value is
 *  mapped to <code>null</code>.  Setting <code>null</code> values will map to
 *  zero (which itself might not be a valid value).
 * </p>
 *
 * <h4>Primitive arrays</h4>
 * <p>
 *  Primitive arrays map to {@link Buffer} types with both the {@link FixedSize}
 *  and {@link ByValue} annotations.  Because of the nature of {@link Buffer}
 *  types, the exact size has to match the native type (that is, there is no way
 *  of specifying, for example, {@link NativeChar} on a {@link Buffer}).
 * </p>
 *
 * <h4>Pointers to primitive arrays (buffers)</h4>
 * <p>
 *  Primitive pointers can map to {@link Buffer} types; for example,
 *  <code>int*</code> can map to {@link IntBuffer}.
 * </p>
 * <h5>Buffers with unknown size</h5>
 * <p>
 *  For unsized buffers (that is, there is no explicit constraint on the buffer
 *  size), there is no getter method.  Instead, there is an update method:
 * </p>
 * <pre>
 *  boolean updateX( IntBuffer buffer );
 *  void setX( IntBuffer buffer );
 * </pre>
 * <p>
 *  The update method will attempt to update the buffer's position to match the
 *  stored pointer.  If the calculated position would be out of range of zero to
 *  the limit, the method does not alter the buffer and returns
 *  <code>false</code>; if the position is updated, it returns
 *  <code>true</code>.  (A hypothetical getter would have to know what size of
 *  buffer is present.  The update method allows buffers to be used safely where
 *  native code updates pointers.)
 * </p>
 * <h5>Buffers with known size</h5>
 * <p>
 *  Buffers may have an explicit size.  The buffer may have a fixed size (a
 *  constant at compile-time).  Alternatively, the size may be determined by
 *  another structure field.  In either case, a getter is possible because the
 *  size of the buffer is known:
 * </p>
 * <pre>
 *  boolean updateX( IntBuffer buffer );
 *  void setX( IntBuffer buffer );
 * </pre>
 * <h5>{@linkplain ByteBuffer#allocateDirect(int) Java-allocated} buffers</h5>
 * <p>
 *  <strong>
 *   You must NOT use Java-allocated direct byte buffers.
 *  </strong>
 *  The lifetime management is too difficult to get correct.  Instead, use
 *  {@link Pointer#allocateBuffer(int)} and explicitly manage the lifetime
 *  yourself.
 * </p>
 *
 * <!-- TODO v1.0 complete this -->
 *
 * <h3>Ordering of fields</h3>
 * <p>
 *  Fields are assumed to be in the order specified in the source file.  Most
 *  compilers honour the ordering, and most VMs honour the ordering of methods
 *  when using reflection.  DNI attempts to locate the original class file and
 *  use the ordering of methods in there.  You can quickly determine if DNI has
 *  the correct ordering by calling {@link #toDebugString()} on an instance.
 *  If the ordering is incorrect, you must annotate each getter with
 *  {@link FieldIndex}.
 * </p>
 *
 *
 * <h3>Unions</h3>
 * <p>
 *  DNI has no specific support for unions.  To simulate the behaviour, create
 *  two structure types (say, <code>A</code> and <code>B</code>) and then define
 *  the union type as a structure:
 * </p>
 * <pre>
 *  interface U extends Structure
 *  {
 *      &#64;ByValue &#64;FieldOffset( 0 )
 *      A getA();
 *
 *      &#64;ByValue &#64;FieldOffset( 0 )
 *      A getB();
 *  }
 * </pre>
 * <p>
 *  The {@link FieldOffset} annotation can be used to create other structure
 *  types where values overlap or have differing types dependent on some other
 *  context.
 * </p>
 *
 * <h3>Lifetime management</h3>
 * <p>
 *  See the notes on {@link NativeObject} about lifetime management.
 * </p>
 * <p>
 *  It is very important that you do not use Java-allocated {@link ByteBuffer}s
 *  (that is, allocated from {@link ByteBuffer#allocateDirect(int)}); the memory
 *  allocated will most likely be freed whilst it is still in use, leading to
 *  random crashes.  Furthermore, the structure's getters methods will return
 *  different buffer instances (but with the same pointer and size) on each
 *  call, which will be confusing.  Instead, use
 *  {@link Pointer#allocateBuffer(int)} and explicitly manage the lifetime
 *  yourself.
 * </p>
 * <p>
 *  Structures may be annotated with a {@link StructureOptions} annotation.
 * </p>
 * <p>
 *  Individual fields may be annotated with various annotations:
 *  {@link FixedSize}, {@link FieldOffset}.  <!-- TODO v1.0 and the rest -->
 * </p>
 * <p>
 *  Note:  Just because an interface is used does not necessarily mean that
 *  any implementation of the interface may be used in this toolkit.  The
 *  only instances used should be those created by factory methods.
 * </p>
 *
 * @author Matthew Wilson
 */
public interface Structure extends FreeableNativeObject
{

    /**
     * <p>
     *  Determines if the given object is a structure of the same type and has
     *  the same values as this structure.
     * </p>
     *
     * @return <code>true</code> iff the given object is equal
     */
    @Override
    boolean equals( Object obj );

    /**
     * <p>
     *  Calculates a hash-code based on the structure's fields.
     * </p>
     * <p>
     *  The hash-code algorithm is implementation-, platform-, and
     *  version-dependent.
     * </p>
     *
     * @return a hash-code
     */
    @Override
    int hashCode();

    /**
     * <p>
     *  Renders the structure into a simple string form for debugging, without
     *  performing any native memory accesses.
     * </p>
     * <p>
     *  The string format is implementation-, platform-, and
     *  version-dependent.
     * </p>
     *
     * @return a string representation
     */
    @Override
    String toString();

    /**
     * <p>
     *  Renders the structure into a string form for debugging.
     * </p>
     * <p>
     *  The string format is implementation-, platform-, and
     *  version-dependent.  This method will access the memory backed by the
     *  structure; if the structure's memory has been deallocated, this method's
     *  behaviour is undefined.
     * </p>
     *
     * @return a string representation
     */
    String toDebugString();

    /**
     * <p>
     *  Allocates a new structure, copying in the values from this structure.
     * </p>
     * <p>
     *  The new structure behaves as though it were created by a
     *  {@link StructureFactory}, with the same burden of memory management.
     * </p>
     *
     * @return a copy
     *
     * @throws UnsupportedOperationException
     *             if this is an opaque structure
     */
    Structure copy();

    /**
     * <p>
     *  Copies all the values from the given structure into this structure.
     * </p>
     *
     * @param other
     *            the other structure
     *
     * @throws ClassCastException
     *             if the other structure is of a different type
     * @throws UnsupportedOperationException
     *             if this is an opaque structure
     */
    void copyFrom( Structure other );

}
